# -*- coding: utf-8 -*-
import pandas as pd
from PySide6.QtCharts import QChart, QChartView, QLineSeries, QValueAxis, QDateTimeAxis, QPieSlice, QPieSeries, \
    QScatterSeries
from PySide6.QtCore import Qt, QDateTime, QPointF
from PySide6.QtGui import QCursor
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel, QTextEdit, QComboBox, QPushButton, QHBoxLayout, QDateEdit, \
    QToolTip

from kumquat_king_pyside6.tools import kumquat_format_converter


class OrderReportPage(QWidget):
    def __init__(self, ordersDF):
        super().__init__()
        self.setWindowTitle("订单报表")
        self.setGeometry(100, 100, 1000, 800)
        self.ordersDf = ordersDF
        self.init_args()
        self.init_ui()
        self.init_slots()

    def init_args(self):
        self.ordersDf['profits'] = self.ordersDf['price'] - \
                                   self.ordersDf['kumquat__original_price'] * self.ordersDf['quantity']
        self.ordersDf['kumquat_name_style'] = kumquat_format_converter(self.ordersDf['kumquat__name'] + ' '
                                                                       + self.ordersDf['kumquat__style'], 'ST2ZH')
        # 准备下拉菜单选项
        self.subject_options = [
            'kumquat',
            'presenter',
            'book_date'
        ]
        self.content_options = [
            'quantity',
            'profits',
            'price'
        ]
        self.time_series_options = [
            'kumquat销量',
            'kumquat价格',
            'kumquat利润',
            'presenter销量',
            'presenter利润',
            'presenter价格'
        ]
        self.min_date = pd.to_datetime(self.ordersDf['book_date']).min().date()
        self.max_date = pd.to_datetime(self.ordersDf['book_date']).max().date()

    def init_ui(self):
        layout = QVBoxLayout()

        chartLayout = QHBoxLayout()
        pieLayout = QVBoxLayout()
        # 第一个下拉菜单：选择饼图的主体
        subjectLayout = QHBoxLayout()
        subjectLabel = QLabel("请选择主体")
        self.subjectCombo = QComboBox()
        self.subjectCombo.addItems(self.subject_options)
        subjectLayout.addWidget(subjectLabel)
        subjectLayout.addWidget(self.subjectCombo)

        # 第二个下拉菜单：选择饼图的内容
        contentLabel = QLabel("请选择主体的展示")
        self.contentCombo = QComboBox()
        self.contentCombo.addItems(self.content_options)
        subjectLayout.addWidget(contentLabel)
        subjectLayout.addWidget(self.contentCombo)
        pieLayout.addLayout(subjectLayout)
        # 生成饼图的按钮
        self.genPieBtn = QPushButton("生成饼图")
        pieLayout.addWidget(self.genPieBtn)

        # 饼图视图
        self.pieChartView = QChartView()
        pieLayout.addWidget(self.pieChartView)
        chartLayout.addLayout(pieLayout)

        # 第二个区域：时间上的数据展示
        timeLayout = QVBoxLayout()

        # 主体选择下拉菜单
        timeSeriesLayout = QHBoxLayout()
        timeSubjectLabel = QLabel("请选择主体")
        self.timeSubjectCombo = QComboBox()
        self.timeSubjectCombo.addItems(self.time_series_options)
        timeSeriesLayout.addWidget(timeSubjectLabel)
        timeSeriesLayout.addWidget(self.timeSubjectCombo)
        timeLayout.addLayout(timeSeriesLayout)

        # 日期选择器
        dateLayout = QHBoxLayout()
        startDateLabel = QLabel("开始日期")
        self.startDateEdit = QDateEdit()
        self.startDateEdit.setDate(self.min_date)
        endDateLabel = QLabel("结束日期")
        self.endDateEdit = QDateEdit()
        self.endDateEdit.setDate(self.max_date)
        dateLayout.addWidget(startDateLabel)
        dateLayout.addWidget(self.startDateEdit)
        dateLayout.addWidget(endDateLabel)
        dateLayout.addWidget(self.endDateEdit)
        timeLayout.addLayout(dateLayout)

        self.genLineChartBtn = QPushButton("生成折线图")
        timeLayout.addWidget(self.genLineChartBtn)

        # 折线图视图
        self.lineChartView = QChartView()
        timeLayout.addWidget(self.lineChartView)

        chartLayout.addLayout(timeLayout)
        layout.addLayout(chartLayout)

        # 第三个区域：文字性区域
        text_area = QTextEdit()
        text_area.setReadOnly(True)
        text_area.setText(self.generate_report_text())
        layout.addWidget(text_area)

        self.setLayout(layout)

    def init_slots(self):
        self.genPieBtn.clicked.connect(self.generate_pie_chart)
        self.genLineChartBtn.clicked.connect(self.generate_line_chart)

    def generate_pie_chart(self):
        subject = self.subjectCombo.currentText()
        content = self.contentCombo.currentText()

        if subject == 'kumquat':
            grouped = self.ordersDf.groupby('kumquat_name_style').sum()[content]
        elif subject == 'presenter':
            grouped = self.ordersDf.groupby('customer__presenter').sum()[content]
        elif subject == 'book_date':
            self.ordersDf['book_date_only'] = pd.to_datetime(self.ordersDf['book_date']).dt.date
            grouped = self.ordersDf.groupby('book_date_only').sum()[content]

        chart = QChart()
        chart.setTitle(f"{subject} 的 {content}")
        chart.setAnimationOptions(QChart.SeriesAnimations)

        series = QPieSeries()
        for index, value in grouped.items():
            sliced = QPieSlice(f"{index}: {value:.2f}", value)
            series.append(sliced)

        chart.addSeries(series)
        series.hovered.connect(self.handle_pie_hover)
        self.pieChartView.setChart(chart)

    def generate_line_chart(self):
        # 清除现有的系列和图例
        self.lineChartView.chart().removeAllSeries()
        self.lineChartView.chart().legend().hide()
        grouped = None
        subject = self.timeSubjectCombo.currentText()
        start_date = self.startDateEdit.date().toPython()
        end_date = self.endDateEdit.date().toPython()

        filtered_df = self.ordersDf[(pd.to_datetime(self.ordersDf['book_date']).dt.date >= start_date) &
                                    (pd.to_datetime(self.ordersDf['book_date']).dt.date <= end_date)]

        chart = QChart()
        chart.setTitle(f"{subject} 随着时间的变化")
        chart.setAnimationOptions(QChart.SeriesAnimations)
        chart.legend().setVisible(True)
        chart.legend().setAlignment(Qt.AlignRight)
        added_series_names = set()

        if subject.startswith('presenter'):
            filtered_df['book_date_only'] = pd.to_datetime(filtered_df['book_date']).dt.date
            if subject.endswith('销量'):
                grouped = filtered_df.groupby(['book_date_only', 'customer__presenter'])['quantity'].sum().unstack(
                    fill_value=0)
            elif subject.endswith('利润'):
                grouped = filtered_df.groupby(['book_date_only', 'customer__presenter'])['profits'].sum().unstack(
                    fill_value=0)
            elif subject.endswith('价格'):
                grouped = filtered_df.groupby(['book_date_only', 'customer__presenter'])['price'].sum().unstack(
                    fill_value=0)

        else:
            filtered_df['book_date_only'] = pd.to_datetime(filtered_df['book_date']).dt.date
            filtered_df['kumquat'] = filtered_df['kumquat__name'] + filtered_df['kumquat__style']
            if subject == 'kumquat销量':
                grouped = filtered_df.groupby(['book_date_only', 'kumquat'])['quantity'].sum().unstack(
                    fill_value=0)
            elif subject == 'kumquat价格':
                grouped = filtered_df.groupby(['book_date_only', 'kumquat'])['price'].sum().unstack(
                    fill_value=0)
            elif subject == 'kumquat利润':
                grouped = filtered_df.groupby(['book_date_only', 'kumquat'])['profits'].sum().unstack(
                    fill_value=0)

        max_value = float('-inf')
        min_value = float('inf')

        for subjectLine, values in grouped.items():
            line_series = QLineSeries()
            scatter_series = QScatterSeries()
            if subjectLine not in added_series_names:
                line_series.setName(subjectLine)
                scatter_series.setName(subjectLine)
                # scatter_series.setMarkerShape(QScatSterSeries.MarkerShapeCircle)
                scatter_series.setMarkerSize(7)

                for date, value in values.items():
                    timestamp = QDateTime(date.year, date.month, date.day, 0, 0, 0).toMSecsSinceEpoch()
                    line_series.append(timestamp, value)
                    scatter_series.append(timestamp, value)
                chart.addSeries(line_series)
                chart.addSeries(scatter_series)

                added_series_names.add(subjectLine)
            if not values.empty:
                max_value = max(max_value, values.max())
                min_value = min(min_value, values.min())

        if max_value != float('-inf') and min_value != float('inf'):
            max_value += max_value * 0.1
            min_value -= min_value * 0.1
            if min_value == 0:
                min_value -= max_value * 0.1
        # 设置轴
        date_axis = QDateTimeAxis()
        date_axis.setTitleText("日期")
        date_axis.setFormat("yyyy-MM-dd")
        date_axis.setRange(QDateTime(start_date.year, start_date.month, start_date.day, 0, 0, 0),
                           QDateTime(end_date.year, end_date.month, end_date.day, 0, 0, 0))
        chart.addAxis(date_axis, Qt.AlignBottom)

        value_axis = QValueAxis()
        value_axis.setTitleText("数值")
        value_axis.setRange(min_value, max_value)
        chart.addAxis(value_axis, Qt.AlignLeft)

        for series in chart.series():
            series.attachAxis(date_axis)
            series.attachAxis(value_axis)
            series.hovered.connect(self.handle_line_hover)

        self.lineChartView.setChart(chart)

    def generate_report_text(self):
        """
        汇总当前的orders信息，按照HTML格式显示如下信息：
        总览
        从start date 到 end date，金桔总销售额为 X 元， 利润为 x 元。
        其中销量最好的是 X 号 X 斤装金桔，销量最差的是 X号 X 斤装 金桔。

        销售者
        卖了最多金桔的销售者【 】， 总销售金额为 X 元。
        之后依次是：....，销售额为 X 元。
        """
        # 计算总销售额和总利润
        total_sales = self.ordersDf['price'].sum()
        total_profits = self.ordersDf['profits'].sum()

        # 计算销量最好的金桔和销量最差的金桔
        self.ordersDf['kumquat'] = self.ordersDf['kumquat__name'] + self.ordersDf['kumquat__style']
        sales_by_kumquat = self.ordersDf.groupby('kumquat')['quantity'].sum()
        best_selling_kumquat = sales_by_kumquat.idxmax() + f"斤装 ({sales_by_kumquat.max()} 份)"
        worst_selling_kumquat = sales_by_kumquat.idxmin() + f"斤装 ({sales_by_kumquat.min()} 份)"

        # 初始化报告文本
        report_text = f"""
           <h1>订单报表</h1>
           <h2>总览</h2>
           <p>从 {self.min_date} 到 {self.max_date}，金桔总销售额为 {total_sales:.2f} 元，
           利润为 {total_profits: .2f} 元， 成本为 {total_sales - total_profits:.2f} 元。</p>
           <p>其中销量最好的是 {best_selling_kumquat}。</p>
           <p>销量最差的是 {worst_selling_kumquat}。</p>
           """

        # 按销售者汇总信息
        presenters = self.ordersDf['customer__presenter'].unique()
        for presenter in presenters:
            presenter_df = self.ordersDf[self.ordersDf['customer__presenter'] == presenter]
            presenter_sales = presenter_df['price'].sum()
            presenter_profits = presenter_df['profits'].sum()

            # 计算每个销售者的销量最好的金桔和销量最差的金桔
            presenter_sales_by_kumquat = presenter_df.groupby('kumquat_name_style')['quantity'].sum()
            presenter_best_selling_kumquat = presenter_sales_by_kumquat.idxmax() + f"斤装 ({presenter_sales_by_kumquat.max()} 份)"
            presenter_worst_selling_kumquat = presenter_sales_by_kumquat.idxmin() + f"斤装 ({presenter_sales_by_kumquat.min()} 份)"

            report_text += f"""
               <h2>销售者: {presenter}</h2>
               <p>总销售额: {presenter_sales:.2f} 元</p>
               <p>总利润: {presenter_profits:.2f} 元</p>
               <p>销量最好的金桔: {presenter_best_selling_kumquat}</p>
               <p>销量最差的金桔: {presenter_worst_selling_kumquat}</p>
               """
        return report_text

    def handle_pie_hover(self, sliced: QPieSlice, state: bool):
        sliced.setExploded(state)
        sliced.setLabelVisible(state)
        pure_label = sliced.label()
        sliced.setLabel(pure_label)

    def handle_line_hover(self, point: QPointF, state: bool):
        if state:
            x = QDateTime.fromMSecsSinceEpoch(int(point.x())).toString("yyyy-MM-dd")
            y = point.y()
            tooltip_text = f"日期: {x}\n值: {y:.2f}"
            QToolTip.showText(QCursor.pos(), tooltip_text)
        else:
            QToolTip.hideText()
